/*********************************************************************
* File: WaypointNavigation.h
*
* Waypoint navigation API. Contains waypoint navigation methods.
*********************************************************************/
#pragma once

#include "../../game/search.h"
#include "Navigation.h"
#include "../interfaces/IWaypointNavigation.h"
using namespace agents::interfaces;

namespace agents{ class Agent; }

namespace agents{ namespace modules{
	class IWaypointHitHandler;

	/**
	* \brief The waypoint navigation module.
	*
	* Supports pathfinding based on waypoint graphs. 
	*
	* \author Instituto Superior Tecnico de Lisboa, Portugal
	* \author Technical University of Lisbon, Portugal
	* 
	* \author Agentes Autonomos e Sistemas Multiagente
	* \author Autonomous Agents and Multiagent Systems
	* 
	* \version	1.0
	* \date		2006/2007
	**/
	class WaypointNavigation: public Navigation, public IWaypointNavigation 
	{
	public:
		WaypointNavigation(Agent &owner);
		~WaypointNavigation();

		//BUG 01: Move to invisible waypoint in the reactive agent: Start
		bool moveToVisibleWaypoint(int waypointIndex);
		//BUG 01: End
		bool moveToWaypoint(int waypointIndex);
		/** 
		* \brief Gets the current waypoint.
		*
		* \see IWaypointNavigation::getCurrentWaypointIndex
		**/
		int getCurrentWaypointIndex(){ return _currentWaypointIndex; }
		/** 
		* \brief Gets the current waypoint destination. 
		*
		* \see IWaypointNavigation::getDestinationWaypointIndex
		**/
		int getDestinationWaypointIndex(){ return _destinationWaypointIndex; }
		/** 
		* \brief Whether a destination has been set. 
		*
		* \see IWaypointNavigation::isDestinationWaypointSet
		**/
		bool isDestinationWaypointSet(){ return _destinationWaypointIndex != -1; }
		bool reachedDestinationWaypoint();
		void stop();
		void hold();

		int getVisibleWaypoints( int* waypoints, int max );
		int getVisibleGoalWaypoints( int* waypoints, int max );
		int getVisibleTerroristImportantWaypoints( int* waypoints, int max );
		int getVisibleCounterTerroristImportantWaypoints( int* waypoints, int max );
		int getVisibleCampWaypoints( int* waypoints, int max );
		Vector getWaypointPosition(int waypoint);
		bool isGoalWaypoint(int waypoint);
		bool isTerroristImportantWaypoint(int waypoint);
		bool isCounterTerroristImportantWaypoint(int waypoint);
		bool isCampWaypoint(int waypoint);

		/** 
		* \brief Sets the A* search cost function.
		*
		* \see IWaypointNavigation::setCostFunction
		**/
		void setCostFunction(float (*function)(int, int))
		{
			_costFunction = function;
		}
		/** 
		* \brief Sets the A* search heuristic function.
		*
		* \see IWaypointNavigation::setCostFunction
		**/
		void setHeuristicFunction(float (*function)(int, int, int))
		{
			_heuristicFunction = function;
		}


		Waypoint** getWaypoints();
		int getNumberOfWaypoints();
		int* getGoalWaypointIndices();
		int getNumberOfGoalWaypoints();
		int* getTerroristImportantWaypointIndices();
		int getNumberOfTerroristImportantWaypoints();
		int* getCounterTerroristImportantWaypointIndices();
		int getNumberOfCounterTerroristImportantWaypoints();
		int* getCampWaypointIndices();
		int getNumberOfCampWaypoints();

		virtual void newRound();
		virtual void startCycle();
		virtual void endCycle();
		
		/** 
		* \brief Gets the current waypoint flags.
		**/
		int getCurrentWaypointFlags(){ return _currentWaypointFlags; }
		/** 
		* \brief Gets the current waypoint connection flags. 
		**/
		unsigned short getCurrentWaypointConnectionFlags(){ return _currentWaypointConnectionFlags; }
		/** 
		* \brief Gets the current waypoint connection velocity.
		**/
		Vector getCurrentWaypointConnectionVelocity(){ return _currentWaypointConnectionVelocity; }
		/** 
		* \brief Gets whether waypoint navigation is automatically updated.
		**/
		bool getIsAutomaticWaypointNavigation(){ return _isAutomaticWaypointNavigation; }
		/** 
		* \brief Sets whether waypoint navigation is automatically updated.
		**/
		void setIsAutomaticWaypointNavigation(bool isAutomatic){ _isAutomaticWaypointNavigation=isAutomatic; }
		/** 
		* \brief Gets the current path root node.
		**/
		game::search::PathNode* getCurrentPathRoot(){ return _waypointPathCurrentNode;}

		IWaypointHitHandler* waypointHitHandler;

	protected:
		bool update();
		void setCurrentWaypointIndex(int index);
		int getClosestReachableWaypoint();
		void validateCurrentWaypoint(void);
		bool findPath(int startIndex, int endIndex);
		void deletePath();
		bool goalIsValid(void);
		bool advanceToNextWaypointInPath(void);
		int getVisibleWaypoints( int* waypoints, int max, WaypointFlags::Enumeration flags );

		/** 
		* \brief Whether agent is presently moving towards a waypoint. 
		**/
		bool _moving;
		/** 
		* \brief Whether waypoint navigation is automatically updated.
		**/
		bool _isAutomaticWaypointNavigation;
		/** 
		* \brief The destination waypoint index.
		**/
		int _destinationWaypointIndex;
		/** 
		* \brief The current waypoint index.
		*
		* The current waypoint is, if the agent is following a path, the next in 
		* path; otherwise, it is simply the closest one. 
		**/
		int _currentWaypointIndex;
		/** 
		* \brief Time the current waypoint index was set.
		**/
		float _currentWaypointTimestamp;
		/** 
		* \brief Previous waypoint indices from waypointfind.
		**/
		int _previousWaypointIndices[5];
		/**
		* \brief The current waypoint flags.
		**/
		int _currentWaypointFlags;
		/** 
		* \brief The current waypoint connection flags (e.g., for jumping).
		**/
		unsigned short _currentWaypointConnectionFlags;
		/** 
		* \brief The current waypoint connection velocity.
		**/
		Vector _currentWaypointConnectionVelocity;
		/**
		* \brief The current waypoint location. 
		**/
		Vector _currentWaypointOrigin;

		/**
		* \brief The A* search cost function. 
		* 
		* By default, it is initialized to ::game::search::costFunctionPathDistance.
		**/
		float (*_costFunction)(int, int);
		/**
		* \brief The A* search heuristic function. 
		* 
		* By default, it is initialized to ::game::search::heuristicFunctionPathDistance.
		**/
		float (*_heuristicFunction)(int, int, int);

		/** 
		* \brief Pointer to current node from the path the agent is following.
		**/
		game::search::PathNode* _waypointPathCurrentNode;
		/** 
		* \brief Pointer to start of pathfinding nodes.
		**/
		game::search::PathNode* _waypointPathRootNode;

	private:
	};

	class IWaypointHitHandler
	{
	public:
		virtual void waypointHit(int index) = 0;
	};
}}